﻿using AutoFixture.Xunit2;
using FluentAssertions;
using Sustainalytics.BusinessResearchProductStates.Entities.ResearchState;
using Sustainalytics.Entities.ScreeningTool;
using System;
using System.Collections.Generic;
using Xunit;

namespace Sustainalytics.Entities.Tests.ScreeningTool
{
    [Trait("Category", "Unit")]
    public class GetResearchState_Should
    {
        private const ResearchState FrameworkNotApplicable = ResearchState.FrameworkNotApplicable;
        private const ResearchState ResearchInProgress = ResearchState.ResearchInProgress;
        private const ResearchState ResearchAvailable = ResearchState.ResearchAvailable;
        private const ResearchState ResearchNotAvailable = ResearchState.ResearchNotAvailable;

        [Theory, AutoData]
        public void Return_ResearchAvailable_when_research_products_is_null(ResearchStates researchStates)
            => ((ResearchProduct[])null).GetResearchState(researchStates).Should().Be(ResearchAvailable);

        [Theory, AutoData]
        public void Return_ResearchAvailable_when_research_products_is_empty(ResearchStates researchStates)
            => (new ResearchProduct[0]).GetResearchState(researchStates).Should().Be(ResearchAvailable);

        [Fact]
        public void Return_FrameworkNotApplicable_when_all_research_states_are_FrameworkNotApplicable_for_the_specified_research_products()
        {
            var researchProducts = new List<ResearchProduct> { ResearchProduct.Core, ResearchProduct.Comprehensive };
            var researchStates = new ResearchStates { CoreEsg = FrameworkNotApplicable, ComprehensiveEsg = FrameworkNotApplicable };

            researchProducts.GetResearchState(researchStates).Should().Be(FrameworkNotApplicable);
        }

        [Theory]
        [InlineData(FrameworkNotApplicable, ResearchInProgress)]
        [InlineData(FrameworkNotApplicable, ResearchAvailable)]
        [InlineData(ResearchInProgress, FrameworkNotApplicable)]
        [InlineData(ResearchInProgress, ResearchInProgress)]
        [InlineData(ResearchInProgress, ResearchAvailable)]
        [InlineData(ResearchAvailable, FrameworkNotApplicable)]
        [InlineData(ResearchAvailable, ResearchInProgress)]
        [InlineData(ResearchAvailable, ResearchAvailable)]
        public void Throw_if_different_research_states_are_available_for_the_specified_research_products(
            ResearchState researchState1, ResearchState researchState2)
        {
            var researchProducts = new List<ResearchProduct> { ResearchProduct.Core, ResearchProduct.Comprehensive };
            var researchStates = new ResearchStates { CoreEsg = researchState1, ComprehensiveEsg = researchState2 };

            Action getResearchStateAction = () => researchProducts.GetResearchState(researchStates);

            getResearchStateAction
                .Should().Throw<InvalidOperationException>()
                .WithMessage("Cannot have more than one research state different from ResearchNotAvailable.");
        }

        [Fact]
        public void Return_research_state_for_corresponding_research_product()
        {
            var researchProducts = new List<ResearchProduct> { ResearchProduct.Controversy };
            var researchStates = new ResearchStates { Controversy = FrameworkNotApplicable };

            researchProducts.GetResearchState(researchStates).Should().Be(FrameworkNotApplicable);
        }

        [Fact]
        public void Return_ResearchNotAvailable_when_there_is_no_available_research_for_corresponding_research_product()
        {
            var researchProducts = new List<ResearchProduct> { ResearchProduct.Controversy };
            var researchStates = new ResearchStates { Controversy = ResearchNotAvailable };

            researchProducts.GetResearchState(researchStates).Should().Be(ResearchNotAvailable);
        }
    }
}
